<?php
/**
 * 	Bushido
 *
 * @category   Bushido
 * @package    Bushido_Db
 * @package    Bushido_Db_Form
 * @copyright  Copyright (c) 2008-2009 Nathan Keyes
 * @author Nathan Keyes
 * @version    $Id: AssemblyLine.php 7 2009-11-14 22:42:08Z nkeyes $
 */

/**
 * 
 * @author Nathan Keyes
 *
 */
class Bushido_Db_Form_AssemblyLine implements RecursiveIterator, ArrayAccess, Countable
{

	protected $_name;
	protected $_dependantSteps;
	protected $_completedUrl;
	
	protected $_position;
	
	public function __construct($config = array())
	{
		$this->_position = 0;
		foreach($config as $key => $value)
		{
			$method = 'set' . ucfirst($key);
			if(method_exists($this, $method))
			{
				call_user_func(array($this, $method), $value);
			}
		}
		
	}
	
	public function __get($key)
	{
		$method = 'get' . ucfirst($key);
		return call_user_func(array($this, $method));
	}
	
	public function __set($key, $value)
	{
		$method = 'set' . ucfirst($key);
		return call_user_func(array($this, $method), $value);
	}
	
	/**
	 * 
	 * @return string
	 */
	public function getName()
	{
		return $this->_name;
	}
	
	/**
	 * 
	 * @param $name string
	 * @return void
	 */
	public function setName($name)
	{
		$this->_name = $name;
	}
	
	/**
	 * 
	 * @param $assemblyLine array
	 * @return unknown_type
	 */
	public function setDependantSteps($dependantSteps)
	{
		if($this->isAssemblyLineValid($dependantSteps))
		{
			$this->_dependantSteps = $dependantSteps;
		}
		else
		{
			throw new Exception('invalid assembly line');
		}
	}
	
	/**
	 * 
	 * @return array
	 */
	public function getDependantSteps()
	{
		return $this->_dependantSteps;
	}
	
	/**
	 * 
	 * @param $assemblyLine array
	 * @return boolean
	 */
	public function isAssemblyLineValid($dependantSteps)
	{
		if(!is_array($dependantSteps) && !($dependantSteps instanceof Bushido_Db_Form_AssemblyLine))
		{
			throw new Exception('Parameter passed to ' . __FUNCTION__ . ' must be an array or an instace of Bushido_Db_Form_AssemblyLine.');
		}
		
		foreach($dependantSteps as $step)
		{
			if($step->getDependantSteps())
			{
				foreach($step->getDependantSteps() as $dependantStep)	
				{
					
					if(!$this->_referenceExists($step->getClass(), $dependantStep->getClass()))
					{
						throw new Exception('No reference between ' . $step->getClass() . ' and ' . $dependantStep->getClass());
						return false;
					}
					elseif(($dependantStep->getDependantSteps()))
					{
						if(!$this->isAssemblyLineValid($dependantStep->getDependantSteps()))
						{
							return false;
						}
					}
				}
			}
		}
		return true;
	}
	
	/**
	 * 
	 * @param $table1
	 * @param $table2
	 * @return boolean
	 */
	protected function _referenceExists($table1, $table2)
	{
		if(!$table1 instanceof Bushido_Db_Table_Abstract)
		{
			$table1 = Bushido_Db_Table::getTable($table1);
		}
		if(!$table2 instanceof Bushido_Db_Table_Abstract)
		{
			$table2 = Bushido_Db_Table::getTable($table2);
		}
		
		foreach(array($table1->getReferenceMap(), $table1->getChildMap()) as $refereceList)
		{
			foreach($refereceList as $reference => $referenceData)
			{
				if(isset($referenceData['refTableClass']) && get_class($table2) == $referenceData['refTableClass'])
				{
					return true;
				}
			}
		}
		return false;
	}

	
	public function rewind()
	{
		$this->_position = 0;
	}

	public function current()
	{
		return $this->_dependantSteps[$this->_position];
	}
	
	public function key()
	{
		return $this->_position;
	}
	
	public function next()
	{
		$this->_position++;
	}
	
	public function valid()
	{
		return isset($this->_dependantSteps[$this->_position]);
	}
	
	public function offsetExists($key)
	{

		return isset($this->_dependantSteps[$key]);
	}
	
	public function offsetGet($key)
	{
		return $this->_dependantSteps[$key];
	}
	
	public function offsetSet($offset, $value)
	{
		if(!$value instanceof Bushido_Db_Form_AssemblyLineStep)
		{
			throw new Exception('Invalid value for dependant step, value must be an instance of Bushido_Db_Form_AssemblyLineStep');
		}
		$this->_dependantSteps[$offset] = $value;
	}
	
	public function offsetUnset($offset)
	{
		unset($this->_dependantSteps[$offset]);
	}
	
	public function hasChildren()
	{
		return count($this->_dependantSteps[$this->_position]->getDependantSteps()) > 0;
	}
	
	public function getChildren()
	{
		return $this->_dependantSteps[$this->_position]->getDependantSteps();
	}
	
	/**
	 * 
	 * @return int
	 */
	public function count()
	{
		$count = count($this->getDependantSteps());
		
		foreach ($this->getDependantSteps() as $dependantStep)
		{
			//Zend_Debug::dump($dependantStep->class, '$dependantStep->class:');
			//Zend_Debug::dump($dependantStep->type, '$dependantStep->type:');
			$count += count($dependantStep);
		}
		return $count;
	}
}